﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using System.Reflection;
using System.Dynamic;
using System.Web;

namespace Super.Common
{
    /// <summary>
    /// HTML 扩展控件
    /// </summary>
    public static class HtmlExtension
    {
        #region 分页控件

        /// <summary>
        /// 分页控件
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="pageSize">单页条数</param>
        /// <param name="currentPage">当前页</param>
        /// <param name="recordCount">总记录数</param>
        /// <param name="attribute">扩展参数</param>
        /// <returns></returns>
        public static MvcHtmlString Pagination(this HtmlHelper helper, Int32 pageSize, Int32 currentPage,
                                               Int32 recordCount, Object attribute)
        {
            /*
             * <span>共：{RecordCount}条 {PageSize}条/页 {CurrentPage}页/{PageCount}页</span> {List}
             * <span>Page {CurrentPage} of {PageCount} ({RecordCount} items) PageSize：{PageSize}</span> {List}
             * @ViewType = 0,   0中文 1英文 2自定义中文 3自定义英文
             * @Template = "<span>共：{RecordCount}条 {PageSize}条/页 {CurrentPage}页/{PageCount}页</span> {List}", 
             * @Postfix = "", 
             * @VirtualPath = "", 
             * @Identifier = "page", 
             * @Encrypt = false }
            */

            if (recordCount <= pageSize)
            {
                return null;
            }

            Int32 ViewType = GetInt32(GetValue(attribute, "ViewType"));
            String Template = GetString(GetValue(attribute, "Template"));
            String Postfix = GetString(GetValue(attribute, "Postfix"));
            String VirtualPath = GetString(GetValue(attribute, "VirtualPath"));
            String Identifier = GetString(GetValue(attribute, "Identifier"));
            String PageOn = GetString(GetValue(attribute, "PageOn"));
            if (Identifier == "")
            {
                Identifier = "page";
            }

            if(PageOn=="")
            {
                PageOn = "curr";
            }

            Boolean Encrypt = GetBoolean(GetValue(attribute, "Encrypt"));
            const string left = "<div class='paged'>";
            const string right = "</div><div class='clear_all'></div>";
            Template = !String.IsNullOrEmpty(Template)
                           ? String.Format(left + "{0}{1}" + right, "\n\t", SetString(Template))
                           : ViewType == 0 || ViewType == 3
                                 ? "\t" + left + "{List}" + right
                                 : "\t" + left + "<span>Page {CurrentPage} of {PageCount} ({RecordCount} items) PageSize：{PageSize}</span> {List}" + right;

            Int32 pagecount = (Int32)Math.Ceiling((Double)recordCount / (Double)pageSize);
            Int32 startPage = 0;
            Int32 endPage = 0;

            if (pagecount <= 5 || currentPage <= 3)
            {
                startPage = 1;
                endPage = 5 > pagecount ? pagecount : 5;
            }
            else
            {
                if (pagecount - currentPage <= 2)
                {
                    startPage = pagecount - 4;
                    endPage = pagecount;
                }
                else
                {
                    startPage = currentPage - 2;
                    endPage = currentPage + 2;
                }
            }

            Postfix = ViewType == 0 || ViewType == 1 ? "" : Postfix;
            StringBuilder html = new StringBuilder();
            String CurrUrl = "";

            if (ViewType == 0 || ViewType == 1)
            {
                CurrUrl = System.Web.HttpContext.Current.Request.RawUrl;
                CurrUrl = DeleteUrlParameter(Identifier);
                Identifier = Identifier + "=";
            }
            else
            {
                CurrUrl = VirtualPath;
                Identifier = "";
            }

            if (currentPage > 1)
            {
                html.AppendFormat("\n\t<a href=\"{0}{1}1\" title=\"{2}\">首页</a>\n\t<a href=\"{0}{1}{3}\" title=\"{4}\">上一页</a>\n",
                    CurrUrl,
                    Identifier,
                    ViewType == 0 || ViewType == 3 ? "首页" : "First",
                    currentPage - 1,
                    ViewType == 0 || ViewType == 3 ? "上一页" : "Previous"
                    );
            }

            if (currentPage > 5)
            {
                html.AppendFormat("\t<a href=\"{0}{1}{2}\" title=\"{3}\">...</a>\n",
                    CurrUrl,
                    Identifier,
                    currentPage - 5,
                    ViewType == 0 || ViewType == 3 ? "上5页" : "Previous Ten Pages");

            }

            for (Int32 j = startPage; j <= endPage; j++)
            {
                html.Append(currentPage == j ? String.Format("\t<a class=\"{0}\" href=\"javascript:void(0)\">{1}</a> \n",PageOn, j) : String.Format("\t<a href=\"{0}{1}{2}\" title=\"{2}\">{2}</a> \n", CurrUrl, Identifier, j));
            }

            if (pagecount - currentPage > 5)
            {
                html.AppendFormat("\t<a href=\"{0}{1}{2}\" title=\"{3}\">....</a>\n",
                    CurrUrl,
                    Identifier,
                    (currentPage + 5),
                    ViewType == 0 || ViewType == 3 ? "下5页" : "Next Ten Pages"
                    );
            }

            if (pagecount > currentPage)
            {
                html.AppendFormat("\t<a href=\"{0}{1}{2}\" title=\"{3}\">下一页</a> \n\t<a href=\"{0}{1}{4}\" title=\"{5}\">末页</a> \n",
                    CurrUrl,
                    Identifier,
                    (currentPage + 1),
                    ViewType == 0 || ViewType == 3 ? "下一页" : "Next",
                    pagecount,
                    ViewType == 0 || ViewType == 3 ? "末页" : "Last"
                    );
            }

            String tx = Template.Replace("{RecordCount}", recordCount.ToString()).Replace("{PageSize}", pageSize.ToString()).Replace("{PageCount}", pagecount.ToString()).Replace("{CurrentPage}", currentPage.ToString()).Replace("{List}", html.ToString());

            return MvcHtmlString.Create(tx);
        }

        #endregion

        #region 通用方法

        /// <summary>
        /// 转成String类型
        /// </summary>
        /// <param name="V"></param>
        /// <returns></returns>
        public static String GetString(Object V)
        {
            return GetString(V, String.Empty);

        }
        /// <summary>
        /// 转成String类型
        /// </summary>
        /// <param name="V"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static String GetString(Object V, String defaultValue)
        {
            if (!IsNull(V))
            {
                return V.ToString().Trim().Replace(">", "&gt;").Replace("<", "&lt;").Replace("'", "&#39;");
            }
            return defaultValue;
        }

        /// <summary>
        /// 是否为空
        /// </summary>
        /// <param name="V"></param>
        /// <returns></returns>
        public static bool IsNull(Object V)
        {
            if (!((V == null) || Convert.IsDBNull(V)))
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 转成Int32类型
        /// </summary>
        /// <param name="V"></param>
        /// <returns></returns>
        public static Int32 GetInt32(Object V)
        {
            return GetInt32(V, 0);
        }
        /// <summary>
        /// 转成Int32类型
        /// </summary>
        /// <param name="V"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static Int32 GetInt32(Object V, Int32 defaultValue)
        {
            if (!(!IsNull(V) && IsInt32(V)))
            {
                return defaultValue;
            }
            return Convert.ToInt32(V);
        }

        /// <summary>
        /// 是否为Int32类型
        /// </summary>
        /// <param name="V"></param>
        /// <returns></returns>
        public static bool IsInt32(Object V)
        {
            try
            {
                Convert.ToInt32(V);
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 转成Boolean类型
        /// </summary>
        /// <param name="V"></param>
        /// <returns></returns>
        public static Boolean GetBoolean(Object V)
        {
            return GetBoolean(V, false);
        }
        /// <summary>
        /// 转成Boolean类型
        /// </summary>
        /// <param name="V"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static Boolean GetBoolean(Object V, Boolean defaultValue)
        {
            if (!(!IsNull(V) && IsBoolean(V)))
            {
                return defaultValue;
            }
            return Convert.ToBoolean(V);
        }
        /// <summary>
        /// 是否为Boolean类型
        /// </summary>
        /// <param name="V"></param>
        /// <returns></returns>
        public static Boolean IsBoolean(Object V)
        {
            try
            {
                Convert.ToBoolean(V);
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 转成String类型
        /// </summary>
        /// <param name="V"></param>
        /// <returns></returns>
        public static String SetString(Object V)
        {
            if (!IsNull(V))
            {
                return V.ToString().Trim().Replace("&gt;", ">").Replace("&lt;", "<").Replace("&#39;", "'");
            }
            return "";
        }
        /// <summary>
        /// 获取扩展参数 { @key = value,@keys = values }
        /// </summary>
        /// <param name="ob"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static String GetValue(Object ob, String key)
        {
            if (ob == null)
            {
                return "";
            }
            String tx = "";
            foreach (PropertyInfo pi in ob.GetType().GetProperties())
            {
                String title = pi.Name;
                if (title == key)
                {
                    tx = pi.GetValue(ob, null).ToString();
                    break;
                }
            }
            return tx;
        }


        /// <summary>
        /// 删除页面参数
        /// </summary>
        /// <param name="P">参数名称</param>
        /// <returns></returns>
        public static String DeleteUrlParameter(String P)
        {
            String S = System.Web.HttpContext.Current.Request.RawUrl;
            S = Regex.Replace(S, @"(?<=.*?\?.+?)&" + P + @"=\d+|(?<=.*?\?)" + P + @"=\d+&|(?<=.*?)\?" + P + @"=\d+$", "");
            return Regex.IsMatch(S, @"\?/g") ? S + "?" : Regex.IsMatch(S, @"(&|\?)") ? S + "&" : S + "?";
        }

        #endregion
    }


    /// <summary> 分页信息.
    /// </summary>
    public class PageInfo
    {
        /// <summary> Name & Key  . 同一页面存在多个分页时标示
        /// </summary>
        public string Key { get; set; }

        /// <summary> 当前页索引 ( 从0开始)
        /// </summary>
        public int PageIndex { get; set; }

        /// <summary> 当前页码 (从 1 开始 )
        /// </summary>
        public int PageNum { get { return PageIndex + 1; } set { PageIndex = value - 1; } }

        /// <summary> 页面大小
        /// </summary>
        public int PageSize { get; set; }

        /// <summary> 元素数量.
        /// </summary>
        public int ItemCount { get; set; }

        /// <summary> 页数
        /// </summary>
        public int PageCount
        {
            get
            {
                if (ItemCount == 0)
                {
                    return 0;
                }
                else
                {
                    return (ItemCount / PageSize) + Math.Min(ItemCount % PageSize, 1);
                }
            }
        }

        /// <summary> 自定义获取Href会调方法
        ///  第一个参数 int 页码(从1开始) 
        ///  第二个参数 string 当前分页的Key
        ///  返回链接的Href.
        /// </summary>
        public Func<int, string, string> CallBackGetHref { get; set; }

        /// <summary> 数据集合
        /// </summary>
        public IEnumerable ItemCollection
        { get; set; }

        /// <summary> 获取Href
        /// </summary>
        /// <param name="linkPageNum"></param>
        /// <returns></returns>
        private string GetHref(int linkPageNum)
        {

            if (CallBackGetHref != null)
            {
                return CallBackGetHref(linkPageNum, Key);
            }
            else
            {
                return URL.GetFull(Key, linkPageNum.ToString());
            }
        }

        /// <summary> 从当前Controller 中获取分页信息.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static PageInfo FromController(string key = null)
        {
            var page = DataCache.NowController;

            foreach (var item in page.ViewData)
            {
                if (item.Value is PageInfo && item.Key == (key ?? item.Key))
                {
                    return item.Value as PageInfo;
                }
            }
            return null;
        }

        /// <summary> 第一页
        /// </summary> 
        /// <param name="disableHtml"></param>
        /// <returns></returns>
        public MvcHtmlString First(string html, string disableHtml = "")
        {
            if (PageCount > 1)
                return new MvcHtmlString(string.Format(PageIndex > 0 ? html : disableHtml, GetHref(1)));
            return null;
        }

        /// <summary> 上一页
        /// </summary>
        /// <param name="html"></param>
        /// <param name="disableHtml"></param>
        /// <returns></returns>
        public MvcHtmlString Previous(string html, string disableHtml = "")
        {
            if (PageCount > 1)
                return new MvcHtmlString(string.Format(PageIndex > 0 ? html : disableHtml, GetHref(PageNum - 1)));
            return null;

        }

        /// <summary> 下一页
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public MvcHtmlString Next(string html, string disableHtml = "")
        {
            if (PageCount > 1)
                return new MvcHtmlString(string.Format(PageNum < PageCount ? html : disableHtml, GetHref(PageNum + 1)));
            return null;
        }

        /// <summary> 最后页
        /// </summary>
        /// <param name="html"></param>
        /// <param name="disableHtml"></param>
        /// <returns></returns>
        public MvcHtmlString Last(string html, string disableHtml = "")
        {
            if (PageCount > 1)
                return new MvcHtmlString(string.Format(PageNum < PageCount ? html : disableHtml, GetHref(PageCount)));
            return null;
        }

        /// <summary> 链接List
        /// </summary>
        /// <param name="html">正常Html 比如 ＜a href='{1}'＞{0}＜/a＞ </param>
        /// <param name="nowPageHtml"></param> 
        /// <param name="splitHtml"></param>
        /// <param name="linkCount"></param>
        /// <returns></returns>
        public MvcHtmlString PageList(string html, string nowPageHtml = null, string splitHtml = "", int linkCount = 10)
        {
            string rt = "";

            var startInx = Math.Max(this.PageIndex - linkCount / 2, 0);

            startInx = Math.Min(startInx, PageCount - linkCount) + 1;

            startInx = Math.Max(1, startInx);

            var loopCount = Math.Min(linkCount, PageCount);
            if (loopCount > 1)
            {
                for (int i = 0; i < loopCount; i++)
                {
                    if (i > 0)
                    {
                        rt += splitHtml;
                    }

                    var pageNum = startInx + i;

                    //如果有模板,则使用模板,,否则按照Key附加.
                    rt += string.Format(pageNum == this.PageNum ? nowPageHtml : html, pageNum, GetHref(pageNum));
                }
            }
            return new MvcHtmlString(rt);
        }

        public MvcHtmlString Begin(string html)
        {
            if (PageCount > 1)
                return new MvcHtmlString(html);
            return null;
        }

        public MvcHtmlString End(string html)
        {
            return Begin(html);
        }

    }

    public static class WebViewPageExtentionMethod
    {
        /// <summary> 获取分页信息
        /// </summary>
        /// <param name="page"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static PageInfo GetPageInfo(this WebViewPage page, string key = null)
        {
            return PageInfo.FromController(key);
        }

        public static IEnumerable<T> GetItemCollection<T>(this WebViewPage page, string key = null)
        {
            return GetPageInfo(page, key).ItemCollection as IEnumerable<T>;
        }

        /// <summary> 输出分页控件
        /// </summary>
        /// <param name="page"> </param>
        /// <param name="attribute">原分页控件的attribute</param>
        /// <param name="key">分页key</param>
        /// <returns></returns>
        public static MvcHtmlString Pagination(this WebViewPage page, object attribute = null, string key = null)
        {
            var pi = GetPageInfo(page, key);

            if (pi != null)
            {
                return HtmlExtension.Pagination(null, pi.PageSize, pi.PageNum, pi.ItemCount, attribute);
            }
            throw new Exception("未发现页面分页信息!");
        }

        /// <summary> 输出分页控件
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="attribute">原分页控件的attribute</param>
        /// <param name="key">分页key</param>
        /// <returns></returns>
        public static MvcHtmlString Pagination(this HtmlHelper htmlHelper, object attribute = null, string key = null)
        {
            return ((WebViewPage)null).Pagination(attribute, key);
        }
    }
}